
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <pthread.h>

#include "ring.h"

RING_MNG *alloc_ring(int num,int size)
{
	int i = 0;
	RING_MNG *ring = malloc(sizeof(RING_MNG));
	if (ring == NULL)
		return NULL;
	memset(ring,0,sizeof(RING_MNG));
	ring->ring_list = malloc(num * sizeof(RING_DESC));
	if (ring->ring_list == NULL)
		return NULL;
	memset(ring->ring_list,0,num*sizeof(RING_DESC));
	if (size > 0)
	{
		for(i = 0;i < num;i++)
		{
			ring->ring_list[i].buff = malloc(size);
			if (ring->ring_list[i].buff == NULL)
			{
				printf("leak memory\n");
				return NULL;
			}
		}
	}
	ring->bsize = size;
	ring->maxnums = num;
	ring->readidx = 0;
	ring->writeidx = 0;
	ring->usednums = 0;

	pthread_mutex_init(&ring->mutext,NULL);
	return ring;
}

void free_ring(RING_MNG *ring)
{
	int i = 0;
	for(i = 0;i < ring->bsize;i++)
	{
		free(ring->ring_list[i].buff);
	}
	free(ring->ring_list);
	free(ring);
}


int add_entry_to_ring(RING_DESC *entry,RING_MNG *ring)
{
	pthread_mutex_lock(&ring->mutext);
	if (ring->maxnums == ring->usednums)
	{
		printf("ring is full\n");
		return -1;
	}
	if (ring->bsize == 0)
		ring->ring_list[ring->writeidx++].address = entry->address;
	else
		memcpy(ring->ring_list[ring->writeidx++].buff,entry->buff,ring->bsize);
	
	if (ring->writeidx >= ring->maxnums)
		ring->writeidx = 0;

	ring->usednums++;
	pthread_mutex_unlock(&ring->mutext);
	return 0;
}

int get_entry_from_ring(RING_DESC *entry,RING_MNG *ring)
{
	pthread_mutex_lock(&ring->mutext);
	if (ring->usednums == 0)
	{
		printf("ring is empty\n");
		return -1;
	}

	if (ring->bsize == 0)
		entry->address = ring->ring_list[ring->readidx++].address;
	else
		memcpy(entry->buff, ring->ring_list[ring->readidx++].buff,ring->bsize);

	if (ring->readidx >= ring->maxnums)
		ring->readidx = 0;

	ring->usednums--;
	pthread_mutex_unlock(&ring->mutext);
	return 0;
}

int is_ring_empty(RING_MNG *ring)
{
	if (ring->usednums)
		return 0;
	else
		return 1;
}

